﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.ViewModel;

namespace CharacterCreation.Data.Models {
    [Serializable]
    public class CharacterSpecial : NotificationObject {

        /// <summary>
        /// Gets or sets the RacialXP
        /// </summary>
        public int RacialXP {
            get { return _RacialXP; }
            set {
                _RacialXP = value;
                RaisePropertyChanged("RacialXP");
                RaisePropertyChanged("TotalXP");
            }
        }
        private int _RacialXP;


        /// <summary>
        /// Gets or sets the ProfessionalXP
        /// </summary>
        public int ProfessionalXP {
            get { return _ProfessionalXP; }
            set {
                _ProfessionalXP = value;
                RaisePropertyChanged("ProfessionalXP");
                RaisePropertyChanged("TotalXP");
            }
        }
        private int _ProfessionalXP;


        /// <summary>
        /// Gets or sets the XP
        /// </summary>
        public int XP {
            get { return _XP; }
            set {
                _XP = value;
                RaisePropertyChanged("XP");
                RaisePropertyChanged("TotalXP");
            }
        }
        private int _XP;


        /// <summary>
        /// Gets or sets the MiscellaneousXP
        /// </summary>
        public int MiscellaneousXP {
            get { return _MiscellaneousXP; }
            set {
                _MiscellaneousXP = value;
                RaisePropertyChanged("MiscellaneousXP");
                RaisePropertyChanged("TotalXP");
            }
        }
        private int _MiscellaneousXP;


        /// <summary>
        /// Gets or sets the MiscellaneousXPReason
        /// </summary>
        public string MiscellaneousXPReason {
            get { return _MiscellaneousXPReason; }
            set {
                _MiscellaneousXPReason = value;
                RaisePropertyChanged("MiscellaneousXPReason");
            }
        }
        private string _MiscellaneousXPReason;


        /// <summary>
        /// Gets or sets the BoughtFrom
        /// </summary>
        public string BoughtFrom {
            get { return _BoughtFrom; }
            set {
                _BoughtFrom = value;
                RaisePropertyChanged("BoughtFrom");
            }
        }
        private string _BoughtFrom;

        /// <summary>
        /// Gets or sets the BoughtXP
        /// </summary>
        public int BoughtXP {
            get { return _BoughtXP; }
            set {
                _BoughtXP = value;
                RaisePropertyChanged("BoughtXP");
            }
        }
        private int _BoughtXP;

        /// <summary>
        /// The total xp spent increasing this skill, statistic or special
        /// </summary>
        public int TotalXP {
            get { return RacialXP + ProfessionalXP + XP + MiscellaneousXP; }
        }

        /// <summary>
        /// Gets or sets the TotalBonus
        /// </summary>
        public int TotalBonus {
            get { return _TotalBonus; }
            set {
                _TotalBonus = value;
                RaisePropertyChanged("TotalBonus");
            }
        }
        private int _TotalBonus;

        /// <summary>
        /// Gets or sets the Skill
        /// </summary>
        public Special Special {
            get { return _Special; }
            set {
                _Special = value;
                RaisePropertyChanged("Special");
            }
        }
        private Special _Special;

        private int startingLevel(Character character) {
            if (Special.Statistics.Count == 0) return 0;

            int total = 0;
            int numberOfStats = 0;
            foreach (string statistic in Special.Statistics) {
                var cStat = character.GetValue<object>(statistic);
                var score = cStat.GetValue<int>("Score");
                numberOfStats = numberOfStats + 1;
                total = total + score;
            }
            return (int)(total / numberOfStats);
        }

        /// <summary>
        /// Gets or sets the Score
        /// </summary>
        public int Score {
            get { return _Score; }
            set {
                _Score = value;
                RaisePropertyChanged("Score");
            }
        }
        private int _Score;


        /// <summary>
        /// override tostring
        /// </summary>
        /// <returns></returns>
        public override string ToString() {
            return this.Special.Name;
        }

        /// <summary>
        /// Calculates the skill level
        /// </summary>
        /// <returns></returns>
        public virtual int CalculateSpecialLevel(Character character) {
            int value = calcSpecialLevel(startingLevel(character), TotalBonus, TotalXP - BoughtXP);
            this.Score = value;
            RaisePropertyChanged("Score");
            return value;
        }

        private int calcSpecialLevel(int start, int totalBonus, int xp) {
            int temp = start;
            while (xp > 0) {
                if (temp < (start * 2) && xp > 0) {
                    temp = temp + 2; xp = xp - 1;
                }
                else if (temp < (start * 3) && xp > 0) {
                    temp = temp + 1; xp = xp - 1;
                }
                else if (temp < (start * 4) && xp > 3) {
                    temp = temp + 2; xp = xp - 3;
                }
                else if (temp < (start * 5) && xp > 2) {
                    temp = temp + 1; xp = xp - 2;
                }
                else if (temp < (start * 6) && xp > 3) {
                    temp = temp + 1; xp = xp - 3;
                }
                else
                    xp = 0;
            }
            return temp + totalBonus;
        }
    }
}
